package com.ihg.hiex.admin.web.controller.session.during;

import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.result.HttpResult;
import com.demo2do.core.utils.CollectionUtils;
import com.demo2do.core.web.interceptor.MenuSetting;
import com.ihg.hiex.admin.entity.dto.Competency;
import com.ihg.hiex.admin.entity.dto.Overall;
import com.ihg.hiex.admin.entity.dto.ReportComment;
import com.ihg.hiex.admin.entity.dto.Swift;
import com.ihg.hiex.admin.entity.security.Login;
import com.ihg.hiex.admin.handler.PDFHandler;
import com.ihg.hiex.admin.handler.ParseHandler;
import com.ihg.hiex.admin.handler.ZipHandler;
import com.ihg.hiex.admin.service.session.CareerWorkService;
import com.ihg.hiex.admin.service.session.ReportWritingService;
import com.ihg.hiex.admin.service.session.SessionDuringService;
import com.ihg.hiex.admin.service.session.SessionParticipatorService;
import com.ihg.hiex.admin.service.session.SessionReportService;
import com.ihg.hiex.admin.service.session.SessionService;
import com.ihg.hiex.admin.service.session.SessionTaskService;
import com.ihg.hiex.admin.web.resolver.Secure;
import com.ihg.hiex.admin.web.view.ExcelTemplateView;
import com.ihg.hiex.entity.session.Session;
import com.ihg.hiex.entity.session.SessionAttribute;
import com.ihg.hiex.entity.session.after.SessionReport;
import com.ihg.hiex.entity.session.before.delegatework.DelegateCareerGoals;
import com.ihg.hiex.entity.session.before.delegatework.DelegateWrokRecord;
import com.ihg.hiex.entity.session.during.SessionCalibration;
import com.ihg.hiex.entity.session.during.SessionCalibrationAnchorScore;
import com.ihg.hiex.entity.session.during.SessionCalibrationComment;
import com.ihg.hiex.entity.session.during.SessionCalibrationCompetency;
import com.ihg.hiex.entity.session.during.SessionCalibrationRecommendation;
import com.ihg.hiex.entity.session.during.report.SessionReportComment;
import com.ihg.hiex.entity.session.during.report.SessionReportCompetency;
import com.ihg.hiex.entity.session.during.report.SessionReportRecommendation;
import com.ihg.hiex.entity.session.during.report.SessionReportWriting;
import com.ihg.hiex.entity.session.participator.SessionParticipator;
import com.ihg.hiex.entity.session.participator.Type;
import com.ihg.hiex.entity.session.task.Status;
import com.ihg.hiex.entity.user.Delegate;

/**
 * 
 * @author dan
 *
 */
@Controller
@RequestMapping("/sessions/{sessionId}/final-reports")
@MenuSetting("menu-sessions")
public class FinalReportController {
    
    @Autowired
    private SessionService sessionService;
    
    @Autowired
    private SessionDuringService sessionDuringService;
    
    @Autowired
    private SessionParticipatorService sessionParticipatorService;
    
    @Autowired
    private SessionTaskService sessionTaskService;
    
    @Autowired
    private SessionReportService sessionReportService;
    
    @Autowired
    private CareerWorkService careerWorkService;
    
    @Autowired
    private ReportWritingService reportWritingService;
    
    @Autowired
    private PDFHandler pdfHandler;
                                
    @Autowired
    private ParseHandler parseHandler;
    
    @Autowired
    private ZipHandler zipHandler;
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(path = "", method = RequestMethod.GET)
    @MenuSetting("submenu-session-after-final-report")
    public ModelAndView list(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/final-report-list");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        if(session.getSessionPhase().isBefore()) {
        	modelAndView.setViewName("session/during/final-report/admin-not-during-error");
        	return modelAndView;
        }
        
        // list assessor subgroup's delegates
        List<SessionParticipator> sessionParticipators = sessionParticipatorService.list(session);
        List<Long> delegateIds = CollectionUtils.extractPropertyList(sessionParticipators, "delegateId");
        
        // list sessionCalibration by delegates
        List<SessionCalibration> sessionCalibrations = sessionDuringService.listSessionCalibration(session, delegateIds);
        modelAndView.addObject("sessionCalibrations", sessionCalibrations);
        
        // list reportWriting map by sessionCalibrationId
        Map<String, SessionReportWriting> reportWritings = sessionReportService.listReportWriting(sessionCalibrations);
        modelAndView.addObject("reportWritings", reportWritings);
        
        // list sessionreport map by delegateId
        Map<String, SessionReport> sessionReports = sessionReportService.list(session);
        modelAndView.addObject("sessionReports", sessionReports);
        
        List<Delegate> delegates = CollectionUtils.extractPropertyList(sessionCalibrations, "delegate");
        Map<Long, Status> reportTaskStatus = sessionTaskService.listCalibrationReportStatus(delegates, session, Type.ASSESSOR, new String[]{"Peer Calibration Competency", "Peer Calibration Comments", "Peer Calibration Recommendation"}, "Peer Calibration");
        modelAndView.addObject("reportTaskStatus", reportTaskStatus);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(path = "/{calibrationId}/report-writing", method = RequestMethod.GET)
    @MenuSetting("submenu-session-after-final-report")
    public ModelAndView reportWriting(@Secure Login login,
                                      @PathVariable("sessionId") Long sessionId,
                                      @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/final-report-report-writing");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        List<SessionCalibrationCompetency> competencies = sessionDuringService.listSessionCalibrationCompetency(sessionCalibration);
        modelAndView.addObject("competencies", competencies);
        
        SessionCalibrationComment comment = sessionDuringService.loadSessionCalibrationComment(sessionCalibration);
        modelAndView.addObject("comment", comment);
        
        SessionCalibrationRecommendation recommendation = sessionDuringService.loadSessionCalibrationRecommendation(sessionCalibration);
        modelAndView.addObject("recommendation", recommendation);
        
        SessionReportWriting sessionReportWriting = sessionReportService.loadReportWriting(sessionCalibration);
        modelAndView.addObject("sessionReportWriting", sessionReportWriting);
        
        // load sessionCalibrationCompetency
        List<SessionCalibrationCompetency> sessionCalibrationCompetencies = sessionDuringService.listSessionCalibrationCompetency(sessionCalibration);
        modelAndView.addObject("sessionCalibrationCompetencies", sessionCalibrationCompetencies);
        
        // list strength and development needs anchorScore
        Map<String, Map<String, List<SessionCalibrationAnchorScore>>> anchorScores = sessionDuringService.listSessionCalibrationAnchorScore(sessionCalibrationCompetencies);
        modelAndView.addObject("anchorScores", anchorScores);
        
        
        return modelAndView;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @MenuSetting(value = "submenu-session-during-development-day")
    @RequestMapping(value = "/{calibrationId}/edit-readiness-recommendation", method = RequestMethod.GET)
    public ModelAndView editReadinessRecommendation(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/readiness-recommendation-edit");
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        SessionReportWriting sessionReportWriting = sessionReportService.loadReportWriting(sessionCalibration);
        modelAndView.addObject("sessionReportWriting", sessionReportWriting);
        
        if(sessionReportWriting == null) {
            SessionCalibrationRecommendation sessionCalibrationRecommendation = sessionDuringService.loadSessionCalibrationRecommendation(sessionCalibration);
            modelAndView.addObject("sessionCalibrationRecommendation", sessionCalibrationRecommendation);
        }
        
        modelAndView.addObject("session", sessionCalibration.getSession());
        
        return modelAndView;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @param recommendation
     * @return
     */
    @RequestMapping(path = "/{calibrationId}/edit-readiness-recommendation", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onEditReadinessRecommendation(@Secure Login login,
                                                                  @PathVariable("sessionId") Long sessionId,
                                                                  @PathVariable("calibrationId") Long calibrationId,
                                                                  SessionReportRecommendation recommendation
                                                                  ) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            
            sessionDuringService.editRecommendation(sessionCalibration, recommendation, login);
            
            httpResult.success().message("Successed");
            
        } catch (Exception e) {
            httpResult.fail("500").message("Failed");
        }
        
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @MenuSetting(value = "submenu-session-during-development-day")
    @RequestMapping(value = "/{calibrationId}/edit-recommendations", method = RequestMethod.GET)
    public ModelAndView editRecommendations(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/development-recommendations-edit");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        SessionReportWriting sessionReportWriting = sessionReportService.loadReportWriting(sessionCalibration);
        modelAndView.addObject("sessionReportWriting", sessionReportWriting);
        
        if(sessionReportWriting == null) {
            // load sessionCalibrationCompetency
            List<SessionCalibrationCompetency> sessionCalibrationCompetencies = sessionDuringService.listSessionCalibrationCompetency(sessionCalibration);
            modelAndView.addObject("sessionCalibrationCompetencies", sessionCalibrationCompetencies);
            
            SessionCalibrationComment comment = sessionDuringService.loadSessionCalibrationComment(sessionCalibration);
            modelAndView.addObject("comment", comment);
            
            Map<String, SessionCalibrationCompetency> competency = CollectionUtils.constructMapValue(sessionCalibrationCompetencies, "name");
            modelAndView.addObject("competency", competency);
        }
        
        modelAndView.addObject("id", sessionId);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param login
     * @param calibrationId
     * @param comment
     * @param reportComment
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/edit-recommendations" , method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onRecommendationSubmit(@Secure Login login,
                                                           @PathVariable("calibrationId") Long calibrationId,
                                                           SessionReportComment comment,
                                                           ReportComment reportComment) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            
//            sessionDuringService.editComment(sessionCalibration, comment, reportComment.getChooseComment(), login);
            
            httpResult.success().message("Successful");
            
        } catch (Exception e) {
            
            httpResult.fail("500").message("Failed");
            
        }
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/edit-effective" , method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ModelAndView editEffective(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
      
      ModelAndView modelAndView = new ModelAndView("session/during/development-day/comptency-effective-supervisor-edit");
      
      SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
      modelAndView.addObject("sessionCalibration", sessionCalibration);
      
      List<SessionCalibrationCompetency> sessionCalibrationCompetencies = sessionDuringService.listSessionCalibrationCompetency(sessionCalibration);
      modelAndView.addObject("sessionCalibrationCompetencies", sessionCalibrationCompetencies);
      
      SessionReportWriting sessionReportWriting = sessionReportService.loadReportWriting(sessionCalibration);
      modelAndView.addObject("sessionReportWriting", sessionReportWriting);
      
      if(sessionReportWriting == null) {
        // load sessionCalibrationCompetency
          
          
          SessionCalibrationComment comment = sessionDuringService.loadSessionCalibrationComment(sessionCalibration);
          modelAndView.addObject("comment", comment);
          
          Map<String, SessionCalibrationCompetency> competency = CollectionUtils.constructMapValue(sessionCalibrationCompetencies, "name");
          modelAndView.addObject("competency", competency);
      }
      
      modelAndView.addObject("id", sessionId);
      
      return modelAndView;
    }
    
    /**
     * 
     * @param login
     * @param calibrationId
     * @param comment
     * @param reportComment
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/edit-effective" , method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onEffectiveSubmit(@Secure Login login,
                                                           @PathVariable("calibrationId") Long calibrationId,
                                                           SessionReportCompetency sessionReportCompetency) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            
            sessionDuringService.editEffective(sessionCalibration, sessionReportCompetency, login);
            
            httpResult.success().message("Successful");
            
        } catch (Exception e) {
            
            httpResult.fail("500").message("Failed");
            
        }
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/report-submit", method = RequestMethod.GET)
    public ModelAndView submitReport(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/report-submit");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        return modelAndView;
        
    }
    
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/report-submit", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onSubmitReport(@Secure Login login,
                                                   @PathVariable("sessionId") Long sessionId,
                                                   @PathVariable("calibrationId") Long calibrationId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            SessionReportWriting sessionReportWriting = sessionReportService.loadReportWriting(sessionCalibration);
            sessionDuringService.adminReportSubmit(sessionReportWriting);
            httpResult.success().message("success");
            
        } catch (BusinessException e) {
            httpResult.fail("500").message(e.getMessage());
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/ppl-report", method = RequestMethod.GET)
    public ModelAndView pplReport(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/ppl-report");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        return modelAndView;
        
    }
    
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/ppl-report", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onPplReport(@Secure Login login,
                                                   @PathVariable("sessionId") Long sessionId,
                                                   @PathVariable("calibrationId") Long calibrationId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            Delegate delegate = sessionCalibration.getDelegate();
            Map<String, SessionAttribute> sessionAtttributes = sessionService.listSessionAttribute(sessionCalibration.getSession(), new String[]{"wave-data", "swift-data"});
            
            // parse waveFile and get competency
            Competency competency = parseHandler.parseWave(delegate.getEmail(), sessionAtttributes.get("wave-data").getValue());
            competency = reportWritingService.getCompetencyScore(sessionCalibration, competency);
            
            // parse swiftFile and get swift
            Swift swift = parseHandler.parseSwift(delegate.getEmail(), sessionAtttributes.get("swift-data").getValue());
            
            // get overall
            Overall overall = reportWritingService.getOverall(sessionCalibration);
            
            // get sessionCalibrationRecommendation
            SessionReportWriting reportWriting = sessionReportService.loadReportWriting(sessionCalibration);
            SessionReportRecommendation recommendation = reportWriting.getSessionReportRecommendation();
            
            String peoplePlanReport = pdfHandler.savePeoplePlaningReport(sessionCalibration.getSession(), delegate, swift, competency, overall, recommendation);
            
            SessionReport sessionReport = sessionReportService.load(sessionCalibration.getSession(), delegate);
            sessionReportService.pplFinalReport(sessionReport, peoplePlanReport);
            httpResult.success().message("success");
            
        } catch (BusinessException e) {
            httpResult.fail("500").message(e.getMessage());
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/delegate-report", method = RequestMethod.GET)
    public ModelAndView delegateReport(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/delegate-report");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        return modelAndView;
        
    }
    
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/delegate-report", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onDelegateReport(@Secure Login login,
                                                   @PathVariable("sessionId") Long sessionId,
                                                   @PathVariable("calibrationId") Long calibrationId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            Delegate delegate = sessionCalibration.getDelegate();
            SessionReport sessionReport = sessionReportService.load(sessionCalibration.getSession(), delegate);
            
            String path = sessionCalibration.getSession().getName() + "/" + delegate.getName() + "/report";
            String zipUrl = zipHandler.zipFile(path, "delegate-final-report", sessionReport);
            sessionReportService.delegateFinalReport(sessionReport, zipUrl);
            
            httpResult.success().message("success");
            
        } catch (BusinessException e) {
            httpResult.fail("500").message(e.getMessage());
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/manager-report", method = RequestMethod.GET)
    public ModelAndView managerReport(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/manager-report");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        return modelAndView;
        
    }
    
    
    /**
     * 
     * @param login
     * @param sessionId
     * @param calibrationId
     * @param english
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/manager-report", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onManagerReport(@Secure Login login,
                                                   @PathVariable("sessionId") Long sessionId,
                                                   @PathVariable("calibrationId") Long calibrationId,
                                                   @RequestParam(value = "english", required = false, defaultValue = "false") boolean english){
        
        HttpResult httpResult = new HttpResult();
        
        try {
        	
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            Delegate delegate = sessionCalibration.getDelegate();
            Map<String, SessionAttribute> sessionAtttributes = sessionService.listSessionAttribute(sessionCalibration.getSession(), new String[]{"wave-data", "swift-data"});
            
            Competency competency = parseHandler.parseWave(delegate.getEmail(), sessionAtttributes.get("wave-data").getValue());
            competency = reportWritingService.getCompetencyScore(sessionCalibration, competency);
            
            List<DelegateWrokRecord> wrokRecords = careerWorkService.listWorkRecord(delegate);
            DelegateCareerGoals goals = careerWorkService.loadCareerGoals(delegate);
            
            SessionReportWriting reportWriting = sessionReportService.loadReportWriting(sessionCalibration);
            SessionReportComment comment = reportWriting.getSessionReportComment();
            
            List<SessionCalibrationCompetency> sessionCalibrationCompetencies = sessionDuringService.listSessionCalibrationCompetency(sessionCalibration);
            SessionReportCompetency sessionReportCompetency = reportWriting.getSessionReportCompetency();
            Map<String, SessionCalibrationCompetency> competencies = CollectionUtils.constructMapValue(sessionCalibrationCompetencies, "name");
            if(sessionReportCompetency != null) {
              competencies = sessionReportCompetency.changeEffective(competencies);
            }
            
            String delegateReport  = pdfHandler.savaDelegateReport(sessionCalibration.getSession(), sessionCalibration.getLeadAssessor(), delegate, wrokRecords, goals, competency, comment, competencies, english);
            
            SessionReport sessionReport = sessionReportService.load(sessionCalibration.getSession(), delegate);
            sessionReportService.managerFinalReport(sessionReport, delegateReport);
            httpResult.success().message("success");
            
        } catch (BusinessException e) {
            httpResult.fail("500").message(e.getMessage());
        } catch (Exception e) {
            httpResult.fail("500").message(e.getMessage());
        }
        
        return httpResult;
    }
    
    /**
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/delegate-report-send", method = RequestMethod.GET)
    public ModelAndView sendDelegateReport(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/delegate-report-send");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        return modelAndView;
        
    }
    
    /**
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/delegate-report-send", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onSendDelegateReport(@Secure Login login,
                                                         @PathVariable("sessionId") Long sessionId,
                                                         @PathVariable("calibrationId") Long calibrationId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            Delegate delegate = sessionCalibration.getDelegate();
            SessionReport sessionReport = sessionReportService.load(sessionCalibration.getSession(), delegate);
            
            sessionReportService.sendDelegateReport(sessionReport);
            
            httpResult.success().message("success");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/manager-report-send", method = RequestMethod.GET)
    public ModelAndView sendManageReport(@Secure Login login, @PathVariable("sessionId") Long sessionId, @PathVariable("calibrationId") Long calibrationId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/manager-report-send");
        
        SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
        modelAndView.addObject("sessionCalibration", sessionCalibration);
        
        return modelAndView;
        
    }
    
    /**
     * @param login
     * @param sessionId
     * @param calibrationId
     * @return
     */
    @RequestMapping(value = "/{calibrationId}/manager-report-send", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onSendManagerReport(@Secure Login login,
                                                        @PathVariable("sessionId") Long sessionId,
                                                        @PathVariable("calibrationId") Long calibrationId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionCalibration sessionCalibration = sessionDuringService.loadSessionCalibration(calibrationId);
            Delegate delegate = sessionCalibration.getDelegate();
            SessionReport sessionReport = sessionReportService.load(sessionCalibration.getSession(), delegate);
            
            sessionReportService.sendManagerReport(sessionReport);
            
            httpResult.success().message("success");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/batch-manager-report", method = RequestMethod.GET)
    public ModelAndView batchManagerReport(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/batch-manager-report");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/batch-manager-report", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onBatchManagerReport(@Secure Login login,
                                                         @PathVariable("sessionId") Long sessionId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            List<SessionReport> sessionReports = sessionReportService.list(session, "managerReport");
            if(!sessionReports.isEmpty()) {
                sessionReportService.batchManagerFinalReport(sessionReports);
            }
            
            httpResult.success().message("success");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/batch-ppl-report", method = RequestMethod.GET)
    public ModelAndView batchPplReport(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/batch-ppl-report");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/batch-ppl-report", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onBatchPplReport(@Secure Login login,
                                                     @PathVariable("sessionId") Long sessionId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            List<SessionReport> sessionReports = sessionReportService.list(session, "pplReport");
            if(!sessionReports.isEmpty()) {
                sessionReportService.batchPplFinalReport(sessionReports);
            }
            
            httpResult.success().message("success");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/batch-delegate-report", method = RequestMethod.GET)
    public ModelAndView batchDelegateReport(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/batch-delegate-report");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    
    /**
     * 
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/batch-delegate-report", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onBatchDelegateReport(@Secure Login login,
                                                          @PathVariable("sessionId") Long sessionId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            List<SessionReport> sessionReports = sessionReportService.list(session, "delegateReport");
            if(!sessionReports.isEmpty()) {
                sessionReportService.batchDelegateFinalReport(sessionReports);
            }
            
            httpResult.success().message("success");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/delegate-report-batch-send", method = RequestMethod.GET)
    public ModelAndView batchSendDelegateReport(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/delegate-report-batch-send");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    /**
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/delegate-report-batch-send", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onBatchSendDelegateReport(@Secure Login login,
                                                         @PathVariable("sessionId") Long sessionId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            List<SessionReport> sessionReports = sessionReportService.listBySendStatus(session, "delegate");
            
            sessionReportService.batchSendDelegateReport(sessionReports);
            
            httpResult.success().message("success");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/manager-report-batch-send", method = RequestMethod.GET)
    public ModelAndView batchSendManagerReport(@Secure Login login, @PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/during/final-report/manager-report-batch-send");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
        
    }
    
    /**
     * @param login
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/manager-report-batch-send", method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onBatchSendManagerReport(@Secure Login login,
                                                         @PathVariable("sessionId") Long sessionId){
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            Session session = sessionService.load(sessionId);
            List<SessionReport> sessionReports = sessionReportService.listBySendStatus(session, "manager");
            
            sessionReportService.batchSendManagerReport(sessionReports);
            
            httpResult.success().message("success");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed..");
        }
        
        return httpResult;
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/report-data-export", method = RequestMethod.GET)
    public ModelAndView onExport(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView(new ExcelTemplateView("report-data.xls", true));
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // list assessor subgroup's delegates
        List<SessionParticipator> sessionParticipators = sessionParticipatorService.list(session);
        List<Long> delegateIds = CollectionUtils.extractPropertyList(sessionParticipators, "delegateId");
        
        // list sessionCalibration by delegates
        List<SessionCalibration> sessionCalibrations = sessionDuringService.listSessionCalibration(session, delegateIds);
        modelAndView.addObject("sessionCalibrations", sessionCalibrations);
        
        String[] competencyNames = new String[]{"成效驱动", "全面协作", "主导变革", "领导和发展员工", "财务管理", "业主关系", "运营管理", "收益最大化"};
        modelAndView.addObject("competencyNames", competencyNames);
        
        // list sessionCalibrationCompetency key->competencyName->sessionCalibrationId
        Map<String, List<SessionCalibrationCompetency>> competencies = sessionDuringService.listCalibrationCompetency(sessionCalibrations);
        modelAndView.addObject("competencies", competencies);
        
        // list sesionCalibrationRecommendation key->sessionCalibrationId
        Map<String, SessionReportWriting> reportWritings = sessionDuringService.listSessionReportWriting(sessionCalibrations);
        modelAndView.addObject("reportWritings", reportWritings);
        
        
        return modelAndView;
        
    }

}
